﻿Imports System.Runtime.InteropServices
Imports System.Drawing.Imaging
Imports System.Drawing
Imports System.Windows.Forms


Public Class clsDibImage

    Structure stBITMAPINFOHEADER '40 bytes
        Dim biSize As Int32                 '14,15,16,17
        Dim biWidth As Int32                '18,19,20,21    
        Dim biHeight As Int32               '22,23,24,25
        Dim biPlanes As Int16
        Dim biBitCount As Int16
        Dim biCompression As Int32
        Dim biSizeImage As Int32
        Dim biXPelsPerMeter As Int32
        Dim biYPelsPerMeter As Int32
        Dim biClrUsed As Int32
        Dim biClrImportant As Int32
    End Structure

    <DllImport("msvfw32.dll")> _
    Private Shared Sub StretchDIB(ByRef biHdrDst As stBITMAPINFOHEADER, _
                                  ByVal DstData As IntPtr, _
                                  ByVal DstX As Int32, _
                                  ByVal DstY As Int32, _
                                  ByVal DstXE As Int32, _
                                  ByVal DstYE As Int32, _
                                  ByRef biHdrSrc As stBITMAPINFOHEADER, _
                                  ByVal SrcData() As Byte, _
                                  ByVal SrcX As Int32, _
                                  ByVal SrcY As Int32, _
                                  ByVal SrcXE As Int32, _
                                  ByVal SrcYE As Int32)
    End Sub

    Private Enum enumStretchMode As Integer
        STRETCH_ANDSCANS = 1
        STRETCH_ORSCANS = 2
        STRETCH_DELETESCANS = 3
        STRETCH_HALFTONE = 4
    End Enum

    <DllImport("gdi32.dll")> _
    Private Shared Function SetStretchBltMode(ByVal hdc As IntPtr, ByVal iStretchMode As enumStretchMode) As Boolean
    End Function

    <DllImport("gdi32.dll")> _
    Private Shared Function StretchDIBits(ByVal hdc As IntPtr, _
                                         ByVal XDest As Integer, _
                                         ByVal YDest As Integer, _
                                         ByVal nDestWidth As Integer, _
                                         ByVal nDestHeight As Integer, _
                                         ByVal XSrc As Integer, _
                                         ByVal YSrc As Integer, _
                                         ByVal nSrcWidth As Integer, _
                                         ByVal nSrcHeight As Integer, _
                                         ByVal lpBits() As Byte, _
                                         ByRef lpBitsInfo As stBITMAPINFOHEADER, _
                                         ByVal iUsage As UInteger, _
                                         ByVal dwRop As UInteger) As Integer
    End Function

    <DllImport("gdi32.dll")> _
    Private Shared Function SetDIBitsToDevice(ByVal hdc As IntPtr, _
                                          ByVal XDest As Int32, _
                                          ByVal YDest As Int32, _
                                          ByVal dwWidth As Int32, _
                                          ByVal dwHeight As Int32, _
                                          ByVal XSrc As Int32, _
                                          ByVal YSrc As Int32, _
                                          ByVal uStartScan As UInt32, _
                                          ByVal cScanLines As UInt32, _
                                          ByVal lpvBits As IntPtr, _
                                          ByRef BITMAPINFO As stBITMAPINFOHEADER, _
                                          ByVal fuColorUse As UInt32) As Int32
    End Function

    'Private Shared IsJPEG As Boolean = False
    'Private Shared tmpBmp As New Bitmap(1920, 1080, Imaging.PixelFormat.Format24bppRgb)
    Private Shared tmpBmp As Bitmap = Nothing
    Public Shared Sub DrawDIB(ByVal dstPicBox As PictureBox, ByVal inSrcBmpByte() As Byte, ByVal camTxt As String)
        Dim dstRc As Rectangle = dstPicBox.ClientRectangle
        If dstRc.Width <= 0 OrElse dstRc.Height <= 0 Then Exit Sub

        Dim dstBiHdrInfo As stBITMAPINFOHEADER
        Dim dstGraph As Graphics = dstPicBox.CreateGraphics
        'Dim srcPicSize As Size = Nothing
        Dim srcBmpByte() As Byte

        'If inSrcBmpByte(0) = &HFF AndAlso inSrcBmpByte(1) = &HD8 Then
        '    IsJPEG = True
        '    Dim JpgPic As New Bitmap(New System.IO.MemoryStream(inSrcBmpByte), False)
        '    srcPicSize = New Size(JpgPic.Width, JpgPic.Height)
        '    srcBmpByte = BmpToBytes(JpgPic)

        'Else
        '    IsJPEG = False
        'srcPicSize = New Size(320, 240)
        ReDim srcBmpByte(inSrcBmpByte.Length - 1)
        Array.Copy(inSrcBmpByte, 0, srcBmpByte, 0, srcBmpByte.Length)
        'End If

        With dstBiHdrInfo
            .biBitCount = 24
            .biCompression = 0
            .biPlanes = 1
            .biSize = 40
            .biWidth = dstRc.Width
            .biHeight = dstRc.Height   '翻轉
            .biSizeImage = System.Math.Abs(.biWidth * .biHeight * 3)
        End With

        Dim srcBiHdrInfo As stBITMAPINFOHEADER
        Dim srcRc As New Rectangle(0, 0, 320, 240)
        With srcBiHdrInfo
            .biBitCount = 24
            .biCompression = 0
            .biPlanes = 1
            .biSize = Marshal.SizeOf(srcBiHdrInfo)
            .biWidth = srcRc.Width
            .biHeight = srcRc.Height
            .biSizeImage = System.Math.Abs(.biWidth * .biHeight * 3)
        End With

        ' 做一張一樣大小的圖檔
        If IsNothing(tmpBmp) OrElse tmpBmp.Width <> dstRc.Width OrElse tmpBmp.Height <> dstRc.Height Then
            tmpBmp = New Bitmap(dstRc.Width, dstRc.Height, PixelFormat.Format24bppRgb)
        End If

        'Stretch
        Dim bd As BitmapData = tmpBmp.LockBits(dstRc, ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb)
        StretchDIB(dstBiHdrInfo, bd.Scan0, dstRc.X, dstRc.Y, dstRc.Width, dstRc.Height, srcBiHdrInfo, srcBmpByte, srcRc.X, srcRc.Y, srcRc.Width, srcRc.Height)
        tmpBmp.UnlockBits(bd)

        ' 顯示攝影機名稱
        If camTxt <> "" Then
            tmpBmp.RotateFlip(RotateFlipType.RotateNoneFlipY)
            Dim g As Graphics = Graphics.FromImage(tmpBmp)
            ShowCamText(g, dstRc.Width, dstRc.Height, camTxt)
            g.Dispose()
            tmpBmp.RotateFlip(RotateFlipType.RotateNoneFlipY)
        End If

        '畫圖
        Dim srcBmpData As BitmapData = tmpBmp.LockBits(dstRc, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb)
        Dim hDC As IntPtr = dstGraph.GetHdc
        SetDIBitsToDevice(hDC, 0, 0, dstRc.Width, dstRc.Height, 0, 0, 0, dstRc.Height, srcBmpData.Scan0, dstBiHdrInfo, 0)
        dstGraph.ReleaseHdc(hDC)
        tmpBmp.UnlockBits(srcBmpData)
        dstGraph.Dispose()
        dstGraph = Nothing
    End Sub

    'Public Shared Sub DrawDIB(ByVal dstPicBox As PictureBox, ByVal inSrcBmpByte() As Byte, ByVal camTxt As String)
    '    Dim showBmp As New Bitmap(New IO.MemoryStream(inSrcBmpByte))
    '    showBmp.RotateFlip(RotateFlipType.RotateNoneFlipY)

    '    '' 顯示攝影機名稱
    '    'If camTxt <> "" Then
    '    '    Dim g As Graphics = Graphics.FromImage(showBmp)
    '    '    Dim srcPicSize As Size = New Size(System.BitConverter.ToInt32(inSrcBmpByte, 18), System.BitConverter.ToInt32(inSrcBmpByte, 22))
    '    '    ShowCamText(g, srcPicSize.Width, srcPicSize.Height, camTxt)
    '    '    'g.Dispose()
    '    'End If

    '    'Dim ggg As Graphics=New 

    '    Dim newBmp As New Bitmap(dstPicBox.ClientSize.Width, dstPicBox.ClientSize.Height, Imaging.PixelFormat.Format24bppRgb)
    '    Dim ggg As Graphics = Graphics.FromImage(newBmp)
    '    ggg.DrawImage(showBmp, dstPicBox.ClientRectangle)
    '    ShowCamText(ggg, dstPicBox.ClientSize.Width, dstPicBox.ClientSize.Height, camTxt)

    '    '畫圖
    '    Dim gg As Graphics = dstPicBox.CreateGraphics
    '    gg.DrawImage(newBmp, dstPicBox.ClientRectangle)
    '    'ShowCamText(gg, dstPicBox.ClientSize.Width, dstPicBox.ClientSize.Height, camTxt)
    'End Sub


    ' 顯示字體
    Public Shared PicFont As New Font("Arial", 14, FontStyle.Bold, GraphicsUnit.Pixel, 1)
    ' 顯示攝影機名稱
    Public Shared Sub ShowCamText(ByRef tGraph As Graphics, ByVal w As Int32, ByVal h As Int32, ByVal txt As String)
        Dim sf As SizeF = tGraph.MeasureString(txt, PicFont)
        Dim x As Int32 = w - sf.Width - 6
        Dim y As Int32 = h - sf.Height - 4
        ShowText(tGraph, txt, x, y, Brushes.Blue)
    End Sub
    '寫字
    Public Shared Sub ShowText(ByRef tGraph As Graphics, ByVal txt As String, ByVal x As Single, ByVal y As Single, ByVal bs As Brush)
        tGraph.DrawString(txt, PicFont, Brushes.White, x - 1, y - 1)
        tGraph.DrawString(txt, PicFont, Brushes.White, x + 1, y - 1)
        tGraph.DrawString(txt, PicFont, Brushes.White, x - 1, y + 1)
        tGraph.DrawString(txt, PicFont, Brushes.White, x + 1, y + 1)
        tGraph.DrawString(txt, PicFont, bs, x, y)
    End Sub

    Public Shared Function BmpToBytes(ByVal bmp As Bitmap) As Byte()
        Dim bData As BitmapData = bmp.LockBits(New Rectangle(New Point(), bmp.Size), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb)
        Dim byteCount As Int32 = bData.Stride * bmp.Height
        Dim bmpBytes(byteCount - 1) As Byte
        Marshal.Copy(bData.Scan0, bmpBytes, 0, byteCount)
        bmp.UnlockBits(bData)
        Return bmpBytes
    End Function

    Public Shared Function BytesToBmp(ByVal bmpBytes() As Byte, ByVal imageSize As Size) As Bitmap
        Dim bmp As Bitmap = New Bitmap(imageSize.Width, imageSize.Height)
        Dim bData As BitmapData = bmp.LockBits(New Rectangle(New Point(), bmp.Size), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb)
        Marshal.Copy(bmpBytes, 0, bData.Scan0, bmpBytes.Length)
        bmp.UnlockBits(bData)
        Return bmp
    End Function
End Class
